use std::net::Ipv4Addr;
use pnet_macros::Packet;
use pnet_macros_support::types::{u16be, u32be};

pub const PROTO_TYPE_BINDING_REQUEST: u8 = 1;
pub const PROTO_TYPE_BINDING_RESPONSE: u8 = 2;
pub const PROTO_TYPE_BINDING_INDICATION: u8 = 3;

pub const HEADER_LEN: usize = HeaderPacket::minimum_packet_size();

#[derive(Packet, Clone)]
pub struct Header {
    _rsvd0: u16be,
    pub version: u8,
    pub typ: u8,

    pub token: u32be,
    pub transaction: u32be,

    #[payload]
    payload: Vec<u8>,
}

pub const BINDING_REQUEST_LEN: usize = BindingRequestPacket::minimum_packet_size();

#[derive(Packet, Clone)]
pub struct BindingRequest {
    #[construct_with(u8, u8, u8, u8)]
    client_vip: Ipv4Addr,

    #[payload]
    payload: Vec<u8>,
}

pub const BINDING_RESPONSE_LEN: usize = BindingResponsePacket::minimum_packet_size();

#[derive(Packet, Clone)]
pub struct BindingResponse {
    #[construct_with(u8, u8, u8, u8)]
    pub client_vip: Ipv4Addr,
    #[construct_with(u8, u8, u8, u8)]
    pub server_vip: Ipv4Addr,
    #[construct_with(u8, u8, u8, u8)]
    pub client_reflex_ip: Ipv4Addr,
    pub client_reflex_port: u16be,

    #[payload]
    payload: Vec<u8>,
}

pub const BINDING_INDICATION_LEN: usize = BindingIndicationPacket::minimum_packet_size();

#[derive(Packet, Clone)]
pub struct BindingIndication {
    #[construct_with(u8, u8, u8, u8)]
    client_vip: Ipv4Addr,
    #[construct_with(u8, u8, u8, u8)]
    server_vip: Ipv4Addr,
    #[construct_with(u8, u8, u8, u8)]
    client_reflex_ip: Ipv4Addr,
    client_reflex_port: u16be,

    #[payload]
    payload: Vec<u8>,
}
